<?php
/**
 * 对任意类型的图片进行缩放和加水印
 **/
class Image
{
    private $path;  // 
    //构造方法用来对图片所在位置进行初始化
    public function __construct($path = './')
    {
        $this->path = rtrim($path, '/') . '/';

    }

    /**对图片进行缩放
        * @param string $srcName: 是需要处理的图片名称
        * @param int $width: 是缩放后的宽度
        * @param int $height: 是缩放后的高度
        * @param string $prefix: 是新图片的名称前缀
        * @return mixed  缩放后的图片的名称， 失败则返回 false
     **/
    public function thumb($srcName, $width, $height, $prefix = 'th_')
    {
        //获取图片信息, 宽度、高度、类型
        $imgInfo = $this->getInfo($srcName);
        //获取图片资源,各种图片都可以生成资源, jpg, png, gif
        $srcImg = $this->getImgSource($srcName, $imgInfo);
        //获取计算后图片等比例大小 $newSize['width'], $newSize['height'] 
        $newSize = $this->getNewSize($width, $height, $imgInfo);
        //获取新的图片资源, 处理gif透明背景
        $newImg = $this->getNewImgSource($srcImg, $newSize, $imgInfo);
        //另存为一个新的图片，返回缩放后的图片名称
        return $this->createNewImage($newImg, $prefix.$srcName, $imgInfo);
    }
    
    /**对图片加水印
        * @param string $srcName: 要加水印的背景图片
        * @param string $waterName: 加水印的图片名
        * @param int $waterPos: 水印的位置  10种状态
        * 0: 随机位置  
        * 1: 顶端居左  2: 顶端居中  3: 顶端居右 
        * 4: 中部居左  5: 中部居中  6: 中部居右 
        * 7: 底端居左  8: 底端居中  9: 底端居右
        * @param string $prefix: 是加水印后新图片的名称前缀
        * @return mixed 处理后的新图片的名称
     **/
    public function addWatermark($srcName, $waterName, $waterPos = 0, $prefix = 'wa_')
    {
        //如果$waterName是一个带目录的地址的图片
        //$dir 水印图片文件 如：./images/clock.jpg  $dir = './images/'
        $dir = dirname($waterName) . '/';  //水印图片如果在当前目录下，$dir = '.', 否则是一个目录
        $waterName = basename($waterName);
        $wpath = $dir . '/';
        //判断图片是否存在
        if (file_exists($this->path.$srcName) && file_exists($wpath.$waterName))  //$wpath 为水印文件的地址
        {
            $srcInfo = $this->getInfo($srcName); //原图的信息
            $waterInfo = $this->getInfo($waterName, $dir);  //水印的图片信息
            //水印的位置，调用私有方法获取水印应该加在原图的哪个位置 $pos 就是位置的数组
            if (!$pos = $this->position($srcInfo, $waterInfo, $waterPos))
            {
                echo '水印不应该比背景图片大！';  
                return false;
            }

            $srcImg = $this->getImgSource($srcName, $srcInfo);  //获取背景图像资源
            $waterImg = $this->getImgSource($waterName, $waterInfo, $dir);   //获取水印图像资源
            
            /*调用私有方法将水印图像按指定位置复制到背景图片中*/
            $srcImg = $this->copyImage($srcImg, $waterImg, $pos, $waterInfo);
            return $this->createNewImage($srcImg, $prefix.$srcName, $srcInfo);

        }
        else
        {
            echo '图片或水印图片不存在！';
            return false;
        } 
    }

    /**
        * 在一个大图片中裁剪出指定区域的图片
        * @param string $srcName  需要裁剪的背景图片
        * @param int $x    裁剪图片左边开始的位置
        * @param int $y    裁剪图片顶部开始的位置
        * @param int $width 图片裁剪的宽度
        * @param int $height 图片裁剪的高度
        * @param string $prefix 新图片的名称前缀
        * @return mixed     裁剪后的图片名称，失败返回false
        **/
    public function cut($srcName, $x, $y, $width, $height, $prefix = 'cu_')
    {
        $srcInfo = $this->getInfo($srcName);
        if ( (($x+$width) > $srcInfo['width']) || (($y+$height) > $srcInfo['height']) )
        {
            echo '裁剪的位置超出了背景图片的范围!';
            return false;
        }
        $srcImg = $this->getImgSource($srcName, $srcInfo);  //获取图片资源
        /*创建一个可以保存裁剪之后的图片资源*/
        $cutImg = imagecreatetruecolor($width, $height);
        imagecopyresampled($cutImg, $srcImg, 0, 0, $x, $y, $width, $height, $width, $height);
        imagedestroy($srcImg); //销毁背景资源
        return $this->createNewImage($cutImg, $prefix.$srcName, $srcInfo);
    }

    /**
     *获取图片信息
     **/
    private function getInfo($srcName, $path = '')
    {
        if ($path == '')
        {
            $spath = $this->path;
        }
        else
        {
            $spath = $path;
        }
        $imageInfo = array();
        $size = getimagesize($spath . $srcName);
        $imageInfo['width'] = $size[0];
        $imageInfo['height'] = $size[1];
        $imageInfo['type'] = $size[2];
        return $imageInfo;
    }

    /**
     * 获取图片资源
     **/
    private function getImgSource($srcName, $imgInfo, $path = '')
    {
        if ($path == '')
        {
           $spath = $this->path; 
        }
        else
        {
           $spath = $path;
        }
        $srcPic = $spath . $srcName;   //$srcPic目标图片的地址及图片名字
        switch ($imgInfo['type'])
        {
            case 1: //gif
                $img = imagecreatefromgif($srcPic);
                break;
            case 2: //jpg
                $img = imagecreatefromjpeg($srcPic);
                break;
            case 3: //png
                $img = imagecreatefrompng($srcPic);
                break;
            default:
                return false;
        }
        return $img;

    }
    /**
     *获取计算后图片等比例大小
     **/
    private function getNewSize($width, $height, $imgInfo)
    {
        $newSize = array();
        $newSize['width'] = $imgInfo['width'];
        $newSize['height'] = $imgInfo['height'];
        
        //原图比要缩放的宽度大才重新设置宽度
        if ($width < $imgInfo['width'])
        {
            $newSize['width'] = $width;
        }
        //原图要比缩放的高度大才重新设置高度
        if ($height < $imgInfo['height'])
        {
            $newSize['height'] = $height;
        }
        //等比例缩放算法
        if ($imgInfo['width']*$newSize['width'] > $imgInfo['height']*$newSize['height'])
        {
            $newSize['height'] = round($imgInfo['height']*$newSize['width']/$imgInfo['width']);
        }
        else
        {
            $newSize['width'] = round($imgInfo['width']*$newSize['height']/$imgInfo['height']);
        } 
        return $newSize;
    }

    /**
     * 做图片缩放时获取新的图片资源 
     **/
    private function getNewImgSource($srcImg, $newSize, $imgInfo)
    {
        $newImg = imagecreatetruecolor($newSize['width'], $newSize['height']);  //画一个图像资源
        $trans_index = imagecolortransparent($srcImg);  //返回原图的透明色
        if ($trans_index >= 0 && $trans_index < imagecolorstotal($srcImg))  
        {  
            //原图有透明色  
            $color_index = imagecolorsforindex($srcImg, $trans_index);  //取得透明色的rgb值  
            //print_r($color_index);  
            //指定透明色颜色  
            $trans_color = imagecolorallocate($img, $color_index['red'], $color_index['green'], $color_index['blue']);  
            imagefill($newImg, 0, 0, $trans_color); //填充新图像资源背景色，但还不是透明色  
            imagecolortransparent($newImg, $trans_color);  //为图像指定透明色  
         }  
        imagecopyresampled($newImg, $srcImg, 0, 0, 0, 0, $newSize['width'], $newSize['height'], 
                           $imgInfo['width'], $imgInfo['height']); 
        imagedestroy($srcImg);
        return $newImg;
    }
    /**
     * 另存为一个新的图片，返回缩放后的图片名称
     **/
    private function createNewImage($newImg, $newName, $imgInfo)
    {
        switch($imgInfo['type'])
        {
            case 1: //gif
                $res = imagegif($newImg, $this->path.$newName);
                break;
            case 2: //jpg
                $res = imagejpeg($newImg, $this->path.$newName);
                break;
            case 3://png
                $res = imagepng($newImg, $this->path.$newName);
                break;
        } 
        imagedestroy($newImg);
        return $newName;
    }
    /**
     * 确定水印图片的位置
     **/
    private function position($srcInfo, $waterInfo, $waterPos)
    {
        //需背景比水印图片大
        if (($srcInfo['width'] < $waterInfo['width']) || ($srcInfo['height'] < $waterInfo['height']))
        {
            return false;
        }
        switch ($waterPos)
        {
            case 1:   //顶端居左
                $posX = 0; 
                $posY = 0;
                break;
            case 2:   //顶端居中
                $posX = ($srcInfo['width'] - $waterInfo['width']) / 2;
                $posY = 0;
                break;
            case 3:   //顶端居右
                $posX = $srcInfo['width'] - $waterInfo['width'];
                $posY = 0;
                break;
            case 4:  //中部居左
                $posX = 0;
                $posY = ($srcInfo['height'] - $waterInfo['height']) / 2;
                break;
            case 5:  //中部居中
                $posX = ($srcInfo['width'] - $waterInfo['width']) / 2;
                $posY = ($srcInfo['height'] - $waterInfo['height']) / 2;
                break;
            case 6:  //中部居右
                $posX = $srcInfo['width'] - $waterInfo['width'];
                $posY = ($srcInfo['height'] - $waterInfo['height']) / 2;
                break;
            case 7:  //底端居左
                $posX = 0;
                $posY = $srcInfo['height'] - $waterInfo['height'];
                break;
            case 8:  //底端居中
                $posX = ($srcInfo['width'] - $waterInfo['width']) / 2;
                $posY = $srcInfo['height'] - $waterInfo['height'];
                break;
            case 9:  //底端居右
                $posX = $srcInfo['width'] - $waterInfo['width'];
                $posY = $srcInfo['height'] - $waterInfo['height']; 
                break;
            case 0:  //随机
            default:
                $posX = mt_rand(0, ($srcInfo['width'] - $waterInfo['width']));
                $posY = mt_rand(0, ($srcInfo['height'] - $srcInfo['height']));
                break;
        }
        return array('posX' => $posX, 'posY' => $posY);
    }

    /**
     * 加水印时copy水印图片
     **/
    private function copyImage($srcImg, $waterImg, $pos, $waterInfo)
    {
        imagecopy($srcImg, $waterImg, $pos['posX'], $pos['posY'], 0, 0, $waterInfo['width'], $waterInfo['height']);
        imagedestroy($waterImg);  //销毁水印信息
        return $srcImg;
    }

}
?>
